﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;
using System.Net;

namespace IPCameHook
{
    public class Hooks
    {
        // -----------------------
        // Этот делегает и есть подключаемая процедура.
        private delegate IntPtr keyboardHookProc(int code, IntPtr wParam, IntPtr lParam);
        // -----------------------
        const int WH_KEYBOARD_LL = 13;  // Номер глобального LowLevel-хука на клавиатуру
        const int WM_KEYDOWN = 0x100;   // Сообщения нажатия клавиши
        // -----------------------
        // Создаем один экземпляр процедуры, назначаем ф-цию для делегата
        private static keyboardHookProc _proc = hookProc;

        // Объект хука
        private static IntPtr hhook = IntPtr.Zero;

        // Это окно, через которое будем показывать флаги
        //private static ShowFlag WindowShowFlag;

        // Идентификатор активного потока
        private static int _ProcessId;

        // Получаем все установленные в систему языки
        private static InputLanguageCollection _InstalledInputLanguages;

        // Текущий язык ввода
        private static string _CurrentInputLanguage;

        public static event EventHandler OnHook;
        public static ParameterizedThreadStart SendRequest;

        // -------------------------
        public static void SetHook()
        {
            // Получаем handle нужной библиотеки
            IntPtr hInstance = LoadLibrary("User32");

            // Ставим LowLevel-hook, обработки клавиатуры, на все потоки
            hhook = SetWindowsHookEx(WH_KEYBOARD_LL, _proc, hInstance, 0);
        }
        // ------------------------
        public static void UnHook()
        {
            // Снятие хука
            UnhookWindowsHookEx(hhook);
        }
        // -----------------------
        // Получение раскладки клавиатуры активного окна
        private static string GetKeyboardLayoutId()
        {
            _InstalledInputLanguages = InputLanguage.InstalledInputLanguages;

            // Получаем хендл активного окна
            IntPtr hWnd = GetForegroundWindow();
            // Получаем номер потока активного окна
            int WinThreadProcId = GetWindowThreadProcessId(hWnd, out _ProcessId);
            // Получаем раскладку
            IntPtr KeybLayout = GetKeyboardLayout(WinThreadProcId);
            // Циклом перебираем все установленные языки для проверки идентификатора
            for (int i = 0; i < _InstalledInputLanguages.Count; i++)
            {
                if (KeybLayout == _InstalledInputLanguages[i].Handle)
                {
                    _CurrentInputLanguage = _InstalledInputLanguages[i].Culture.ThreeLetterWindowsLanguageName.ToString();
                }
            }
            return _CurrentInputLanguage;
        }
        
        
        // ---------------------------
        // Вот и наша подключаемая процедура.
        // Здесь мы будем обрабатывать сообщения клавиатуры
        public static IntPtr hookProc(int code, IntPtr wParam, IntPtr lParam)
        {
            if (code >= 0 && wParam == (IntPtr)0x101)
            {
                int vkCode = Marshal.ReadInt32(lParam);                

                string url = "";
                string str = "";

                Debug.WriteLine(vkCode.ToString());

                switch (vkCode)
                {
                    case 35:case 97:  
                        {
                            str = "Включение камеры 1";                            
                            url = @"http://" + ipcamehotKey.Properties.Settings.Default.IPCame1 + "/dev/gpioCtrl.cgi?out1=1"; 
                        } 
                        break;
                    case 36:case 103: 
                        {
                            str = "Включение камеры 3";                            
                            url = @"http://" + ipcamehotKey.Properties.Settings.Default.IPCame3 + "/dev/gpioCtrl.cgi?out1=1"; 
                        } 
                        break;
                    case 37:case 100: 
                        {
                            str = "Включение камеры 2";                            
                            url = @"http://" + ipcamehotKey.Properties.Settings.Default.IPCame3 + "/dev/gpioCtrl.cgi?out1=1"; 
                        } 
                        break;

                    case 40:case 98:  
                        {
                            str = "Выключение камеры 1";  
                            url = @"http://" + ipcamehotKey.Properties.Settings.Default.IPCame1 + "/dev/gpioCtrl.cgi?out1=0"; 
                        } 
                        break;
                    case 12:case 101: 
                        {
                            str = "Выключение камеры 2";  
                            url = @"http://" + ipcamehotKey.Properties.Settings.Default.IPCame2 + "/dev/gpioCtrl.cgi?out1=0"; 
                        } 
                        break;
                    case 38:case 104: 
                        {
                            str = "Выключение камеры 3";  
                            url = @"http://" + ipcamehotKey.Properties.Settings.Default.IPCame3 + "/dev/gpioCtrl.cgi?out1=0"; 
                        } 
                        break;

                    default: url = ""; break;
                }

                try
                {
                    if (url != "")
                    {
                        if (OnHook != null) { OnHook((object)str, new EventArgs()); }
                        Thread _thRequest = new Thread(SendRequest);
                        object[] _data = new object[2] {url,str}; 
                        _thRequest.Start(_data);                        
                    }
                }
                catch (Exception Ex)
                {
                    if (OnHook != null) { OnHook((object)url+"\r\n"+Ex.Message, new EventArgs()); }
                }                

            }
            return CallNextHookEx(hhook, code, (int)wParam, lParam);
        }
        // ----------------------------
        // Импорт нужных WinApi-функций
        [DllImport("user32.dll")]
        static extern IntPtr SetWindowsHookEx(int idHook, keyboardHookProc callback, IntPtr hInstance, uint threadId);

        [DllImport("user32.dll")]
        static extern bool UnhookWindowsHookEx(IntPtr hInstance);

        [DllImport("user32.dll")]
        static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, int wParam, IntPtr lParam);

        [DllImport("kernel32.dll")]
        static extern IntPtr LoadLibrary(string lpFileName);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern int GetWindowThreadProcessId(IntPtr handleWindow, out int lpdwProcessID);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern IntPtr GetKeyboardLayout(int WindowsThreadProcessID);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr GetForegroundWindow();

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr SetForegroundWindow(IntPtr hWnd);
    }
}